package org.jeecg.modules.engine.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.jeecg.common.system.query.QueryGenerator;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.engine.entity.Task;
import org.jeecg.modules.engine.entity.vo.FrameTotalVo;
import org.jeecg.modules.engine.entity.vo.FrameVo;
import org.jeecg.modules.engine.service.ITaskService;
import org.jeecg.modules.flow.entity.Flow;
import org.jeecg.modules.flow.entity.FlowDetail;
import org.jeecg.modules.flow.service.IFlowDetailService;
import org.jeecg.modules.flow.service.IFlowService;
import org.jeecg.modules.procedure.entity.Proc;
import org.jeecg.modules.procedure.service.IProcService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;

import java.text.SimpleDateFormat;
import java.util.*;

import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.engine.entity.Frame;
import org.jeecg.modules.engine.entity.Requirement;
import org.jeecg.modules.engine.entity.Engineering;
import org.jeecg.modules.engine.service.IEngineeringService;
import org.jeecg.modules.engine.service.IFrameService;
import org.jeecg.modules.engine.service.IRequirementService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.io.IOException;
import java.util.stream.Collectors;

 /**
 * @Description: 工程表
 * @Author: jeecg-boot
 * @Date:   2020-07-20
 * @Version: V1.0
 */
@Api(tags="工程表")
@RestController
@RequestMapping("/engine/engineering")
@Slf4j
public class EngineeringController extends JeecgController<Engineering, IEngineeringService> {

	@Autowired
	private IEngineeringService engineeringService;

	@Autowired
	private IFrameService frameService;

	@Autowired
	private IRequirementService requirementService;

	@Autowired
	private ITaskService taskService;

	@Autowired
	private IFlowService flowService;

	@Autowired
	private IFlowDetailService flowDetailService;

	@Autowired
	private IProcService procService;


	/*---------------------------------主表处理-begin-------------------------------------*/

	/**
	 * 分页列表查询
	 * @param engineering
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	@AutoLog(value = "工程表-分页列表查询")
	@ApiOperation(value="工程表-分页列表查询", notes="工程表-分页列表查询")
	@GetMapping(value = "/list")
	public Result<?> queryPageList(Engineering engineering,
								   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
								   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
		LambdaQueryWrapper<Engineering> queryWrapper = new LambdaQueryWrapper<Engineering>();
		if(engineering.getEngineCode()!=null && !engineering.getEngineCode().equals("")){
			queryWrapper = queryWrapper.like(Engineering::getEngineCode,engineering.getEngineCode());
		}
		if (engineering.getEngineName() != null && !engineering.getEngineName().equals("")){
			queryWrapper = queryWrapper.like(Engineering::getEngineName,engineering.getEngineName());
		}
		queryWrapper.orderByDesc(Engineering::getCreateTime);
		Page<Engineering> page = new Page<Engineering>(pageNo, pageSize);
		IPage<Engineering> pageList = engineeringService.page(page, queryWrapper);
		return Result.ok(pageList);
	}

	 /**
	  * 分页列表查询
	  * @param frameVo
	  * @param pageNo
	  * @param pageSize
	  * @return
	  */
	 @AutoLog(value = "构件表-分页列表查询")
	 @ApiOperation(value="工程表-分页列表查询", notes="工程表-分页列表查询")
	 @GetMapping(value = "/frame_list")
	 public Result<?> frameQueryPageList(FrameVo frameVo,
										 @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
										 @RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
		 Page<FrameVo> page = new Page<FrameVo>(pageNo, pageSize);
		 IPage<FrameVo> pageList = frameService.selectFramePage(page, frameVo);
		 return Result.ok(pageList);
	 }

	/**
     *   添加
     * @param engineering
     * @return
     */
    @AutoLog(value = "工程表-添加")
    @ApiOperation(value="工程表-添加", notes="工程表-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody Engineering engineering) {
        engineeringService.save(engineering);
        return Result.ok("添加成功！");
    }

    /**
     *  编辑
     * @param engineering
     * @return
     */
    @AutoLog(value = "工程表-编辑")
    @ApiOperation(value="工程表-编辑", notes="工程表-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody Engineering engineering) {
        engineeringService.updateById(engineering);
        return Result.ok("编辑成功!");
    }

    /**
     * 通过id删除
     * @param id
     * @return
     */
    @AutoLog(value = "工程表-通过id删除")
    @ApiOperation(value="工程表-通过id删除", notes="工程表-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> deleteEngineer(@RequestParam(name="id",required=true) String id) {
        engineeringService.delMain(id);
        return Result.ok("删除成功!");
    }

    /**
     * 批量删除
     * @param ids
     * @return
     */
    @AutoLog(value = "工程表-批量删除")
    @ApiOperation(value="工程表-批量删除", notes="工程表-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
        this.engineeringService.delBatchMain(Arrays.asList(ids.split(",")));
        return Result.ok("批量删除成功!");
    }

    /**
     * 导出
     * @return
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, Engineering engineering) {
        return super.exportXls(request, engineering, Engineering.class, "工程表");
    }

    /**
     * 导入
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        return super.importExcel(request, response, Engineering.class);
    }
	/*---------------------------------主表处理-end-------------------------------------*/


    /*--------------------------------子表处理-构件表-begin----------------------------------------------*/
	/**
	 * 通过主表ID查询
	 * @return
	 */
	@AutoLog(value = "构件表-通过主表ID查询")
	@ApiOperation(value="构件表-通过主表ID查询", notes="构件表-通过主表ID查询")
	@GetMapping(value = "/listFrameByMainId")
    public Map<String, Object> listFrameByMainId(Frame frame,
												 @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
												 @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
												 HttpServletRequest req) {
        Page<Frame> page = new Page<Frame>(pageNo, pageSize);
        IPage<Frame> pageList = frameService.framePage(page, frame);
		Map<String,Object> resultMap = new HashMap<>();
		resultMap.put("success",true);
		resultMap.put("code",200);
		resultMap.put("result",pageList);
        if (pageList.getRecords()!=null && pageList.getRecords().size()>0){
			FrameTotalVo frameTotalVo = frameService.frameTotal(frame);
			if (frameTotalVo!=null && frameTotalVo.getTotalWeight() != null){
				resultMap.put("totalWeight",frameTotalVo.getTotalWeight());
			}
			if (frameTotalVo!=null && frameTotalVo.getTotalCount() != null){
				resultMap.put("totalCount",frameTotalVo.getTotalCount());
			}
			if (frameTotalVo!=null && frameTotalVo.getTotalArea() != null){
				resultMap.put("totalArea",frameTotalVo.getTotalArea());
			}
		}
		return resultMap;
    }


	 /**
	  * 通过主表ID查询
	  * @return
	  */
	 @AutoLog(value = "任务表-通过主表ID查询")
	 @ApiOperation(value="任务表-通过主表ID查询", notes="任务表-通过主表ID查询")
	 @GetMapping(value = "/listTaskByMainId")
	 public Result<?> listTaskByMainId(Task task,
									   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
									   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
									   HttpServletRequest req) {
		 Map<String, String[]> parameterMap = new HashMap<>(req.getParameterMap());
		 parameterMap.remove("order");
		 QueryWrapper<Task> queryWrapper = QueryGenerator.initQueryWrapper(task, parameterMap);
		 queryWrapper.orderByAsc("handle_sort");
		 Page<Task> page = new Page<Task>(pageNo, pageSize);
		 IPage<Task> pageList = taskService.page(page, queryWrapper);
		 return Result.ok(pageList);
	 }


	/**
	 * 添加
	 * @param frame
	 * @return
	 */
	@AutoLog(value = "构件表-添加")
	@ApiOperation(value="构件表-添加", notes="构件表-添加")
	@PostMapping(value = "/addFrame")
	@Transactional
	public Result<?> addFrame(@RequestBody Frame frame) {
		List<FlowDetail> flowDetails = flowDetailService.list(new LambdaQueryWrapper<FlowDetail>().eq(FlowDetail::getFlowId, frame.getFlowId()));

		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
		String currDay = simpleDateFormat.format(new Date());
		final int[] count = {taskService.count(new LambdaQueryWrapper<Task>().ge(Task::getCreateTime, currDay + " 00:00:00").and(p -> p.le(Task::getCreateTime, currDay + " 23:59:59")))};
		String prefix = "WK";
		String dateFormat = new SimpleDateFormat("yyyyMMdd").format(new Date());
		frame.setDoneCount(0);
		frame.setStatus(1);
		frame.setIsEnable(1);
		frameService.save(frame);
		List<String> procIds = flowDetails.stream().map(FlowDetail::getProcId).collect(Collectors.toList());
		List<Proc> procList = procService.list(new LambdaQueryWrapper<Proc>().in(Proc::getId, procIds));

		flowDetails.forEach(flowDetail -> {
			Task task = new Task();
			count[0]=count[0]+1;
			String code = prefix+dateFormat+String.format("%04d", count[0]);
			task.setTaskNo(code);
			task.setFramId(frame.getId());
			task.setProcId(flowDetail.getProcId());
			task.setHandleSort(flowDetail.getSort());
			Proc currProc = procList.stream().filter(proc -> proc.getId().equals(flowDetail.getProcId())).findFirst().get();


			task.setProcCode(currProc.getCode());
			task.setProcName(currProc.getName());
			task.setTaskCount(frame.getCount());
			if (flowDetail.getSort() == 1){
				task.setInProcCount(frame.getCount());
			}else {
				task.setInProcCount(0);
			}
			task.setEligibilityCount(0);
			task.setReportCount(0);
			taskService.save(task);
		});
		return Result.ok("添加成功！");
	}

    /**
	 * 编辑
	 * @param frame
	 * @return
	 */
	@AutoLog(value = "构件表-编辑")
	@ApiOperation(value="构件表-编辑", notes="构件表-编辑")
	@PutMapping(value = "/editFrame")
	public Result<?> editFrame(@RequestBody Frame frame) {
		frameService.updateById(frame);
		return Result.ok("编辑成功!");
	}

	/**
	 * 通过id删除
	 * @param id
	 * @return
	 */
	@AutoLog(value = "构件表-通过id删除")
	@ApiOperation(value="构件表-通过id删除", notes="构件表-通过id删除")
	@DeleteMapping(value = "/deleteFrame")
	public Result<?> deleteFrame(@RequestParam(name="id",required=true) String id) {
		Boolean deleteFrame = frameService.deleteFrame(id);
		if (deleteFrame){
			return Result.ok("删除成功!");
		}
		return Result.error("已有报工数据，不能删除");
	}

	/**
	 * 批量删除
	 * @param ids
	 * @return
	 */
	@AutoLog(value = "构件表-批量删除")
	@ApiOperation(value="构件表-批量删除", notes="构件表-批量删除")
	@DeleteMapping(value = "/deleteBatchFrame")
	public Result<?> deleteBatchFrame(@RequestParam(name="ids",required=true) String ids) {
		return frameService.deleteBatchFrame(ids);
	}

    /**
     * 导出
     * @return
     */
    @RequestMapping(value = "/exportFrame")
    public ModelAndView exportFrame(HttpServletRequest request, Frame frame) {
		 // Step.1 组装查询条件
		 QueryWrapper<Frame> queryWrapper = QueryGenerator.initQueryWrapper(frame, request.getParameterMap());
		 LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

		 // Step.2 获取导出数据
		 List<Frame> pageList = frameService.list(queryWrapper);
		 List<Frame> exportList = null;

		 // 过滤选中数据
		 String selections = request.getParameter("selections");
		 if (oConvertUtils.isNotEmpty(selections)) {
			 List<String> selectionList = Arrays.asList(selections.split(","));
			 exportList = pageList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
		 } else {
			 exportList = pageList;
		 }

		 // Step.3 AutoPoi 导出Excel
		 ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
		 mv.addObject(NormalExcelConstants.FILE_NAME, "构件表"); //此处设置的filename无效 ,前端会重更新设置一下
		 mv.addObject(NormalExcelConstants.CLASS, Frame.class);
		 mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("构件表报表", "导出人:" + sysUser.getRealname(), "构件表"));
		 mv.addObject(NormalExcelConstants.DATA_LIST, exportList);
		 return mv;
    }

    /**
     * 导入
     * @return
     */
    @RequestMapping(value = "/importFrame/{mainId}")
    public Result<?> importFrame(HttpServletRequest request, HttpServletResponse response, @PathVariable("mainId") String mainId) {
		 MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		 Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
		Map<String,String> flowMap = new HashMap<>();
		List<Flow> flowList = flowService.list();
		flowList.forEach(flow -> {
			flowMap.put(flow.getFlowName(),flow.getId());
		});
		 for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
			 MultipartFile file = entity.getValue();// 获取上传文件对象
			 ImportParams params = new ImportParams();
			 params.setTitleRows(2);
			 params.setHeadRows(1);
			 params.setNeedSave(true);
			 try {
				 List<Frame> list = ExcelImportUtil.importExcel(file.getInputStream(), Frame.class, params);
				 for (Frame temp : list) {
                    temp.setEngineeringId(mainId);
                    temp.setFlowId(flowMap.get(temp.getFlowName()));
				 }
				 long start = System.currentTimeMillis();
				 frameService.saveBatch(list);
				 log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
				 return Result.ok("文件导入成功！数据行数：" + list.size());
			 } catch (Exception e) {
				 log.error(e.getMessage(), e);
				 return Result.error("文件导入失败:" + e.getMessage());
			 } finally {
				 try {
					 file.getInputStream().close();
				 } catch (IOException e) {
					 e.printStackTrace();
				 }
			 }
		 }
		 return Result.error("文件导入失败！");
    }

    /*--------------------------------子表处理-构件表-end----------------------------------------------*/

    /*--------------------------------子表处理-需求表-begin----------------------------------------------*/
	/**
	 * 通过主表ID查询
	 * @return
	 */
	@AutoLog(value = "需求表-通过主表ID查询")
	@ApiOperation(value="需求表-通过主表ID查询", notes="需求表-通过主表ID查询")
	@GetMapping(value = "/listRequirementByMainId")
    public Result<?> listRequirementByMainId(Requirement requirement,
                                                    @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                    @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                                    HttpServletRequest req) {
        QueryWrapper<Requirement> queryWrapper = QueryGenerator.initQueryWrapper(requirement, req.getParameterMap());
        Page<Requirement> page = new Page<Requirement>(pageNo, pageSize);
        IPage<Requirement> pageList = requirementService.page(page, queryWrapper);
        return Result.ok(pageList);
    }

	/**
	 * 添加
	 * @param requirement
	 * @return
	 */
	@AutoLog(value = "需求表-添加")
	@ApiOperation(value="需求表-添加", notes="需求表-添加")
	@PostMapping(value = "/addRequirement")
	public Result<?> addRequirement(@RequestBody Requirement requirement) {
		requirementService.saveRequirement(requirement);
		return Result.ok("添加成功！");
	}

    /**
	 * 编辑
	 * @param requirement
	 * @return
	 */
	@AutoLog(value = "需求表-编辑")
	@ApiOperation(value="需求表-编辑", notes="需求表-编辑")
	@PutMapping(value = "/editRequirement")
	public Result<?> editRequirement(@RequestBody Requirement requirement) {
		requirementService.updateRequirment(requirement);
		return Result.ok("编辑成功!");
	}

	/**
	 * 通过id删除
	 * @param id
	 * @return
	 */
	@AutoLog(value = "需求表-通过id删除")
	@ApiOperation(value="需求表-通过id删除", notes="需求表-通过id删除")
	@DeleteMapping(value = "/deleteRequirement")
	public Result<?> deleteRequirement(@RequestParam(name="id",required=true) String id) {
		requirementService.deleteRequirmentById(id);
		return Result.ok("删除成功!");
	}

	/**
	 * 批量删除
	 * @param ids
	 * @return
	 */
	@AutoLog(value = "需求表-批量删除")
	@ApiOperation(value="需求表-批量删除", notes="需求表-批量删除")
	@DeleteMapping(value = "/deleteBatchRequirement")
	public Result<?> deleteBatchRequirement(@RequestParam(name="ids",required=true) String ids) {
	    return requirementService.deleteBatchRequirement(Arrays.asList(ids.split(",")));
	}

    /**
     * 导出
     * @return
     */
    @RequestMapping(value = "/exportRequirement")
    public ModelAndView exportRequirement(HttpServletRequest request, Requirement requirement) {
		 // Step.1 组装查询条件
		 QueryWrapper<Requirement> queryWrapper = QueryGenerator.initQueryWrapper(requirement, request.getParameterMap());
		 LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		// Step.2 获取导出数据
		 List<Requirement> pageList = requirementService.list(queryWrapper);
		 List<Requirement> exportList = null;

		 // 过滤选中数据
		 String selections = request.getParameter("selections");
		 if (oConvertUtils.isNotEmpty(selections)) {
			 List<String> selectionList = Arrays.asList(selections.split(","));
			 exportList = pageList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
		 } else {
			 exportList = pageList;
		 }

		 // Step.3 AutoPoi 导出Excel
		 ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
		 mv.addObject(NormalExcelConstants.FILE_NAME, "需求表"); //此处设置的filename无效 ,前端会重更新设置一下
		 mv.addObject(NormalExcelConstants.CLASS, Requirement.class);
		 mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("需求表报表", "导出人:" + sysUser.getRealname(), "需求表"));
		 mv.addObject(NormalExcelConstants.DATA_LIST, exportList);
		 return mv;
    }

    /**
     * 导入
     * @return
     */
    @RequestMapping(value = "/importRequirement/{mainId}")
    public Result<?> importRequirement(HttpServletRequest request, HttpServletResponse response, @PathVariable("mainId") String mainId) {
		 MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		 Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
		 for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
			 MultipartFile file = entity.getValue();// 获取上传文件对象
			 ImportParams params = new ImportParams();
			 params.setTitleRows(2);
			 params.setHeadRows(1);
			 params.setNeedSave(true);
			 try {
				 List<Requirement> list = ExcelImportUtil.importExcel(file.getInputStream(), Requirement.class, params);
				 for (Requirement temp : list) {
                    temp.setEngineeringId(mainId);
				 }
				 long start = System.currentTimeMillis();
				 requirementService.saveBatch(list);
				 log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
				 return Result.ok("文件导入成功！数据行数：" + list.size());
			 } catch (Exception e) {
				 log.error(e.getMessage(), e);
				 return Result.error("文件导入失败:" + e.getMessage());
			 } finally {
				 try {
					 file.getInputStream().close();
				 } catch (IOException e) {
					 e.printStackTrace();
				 }
			 }
		 }
		 return Result.error("文件导入失败！");
    }

    /*--------------------------------子表处理-需求表-end----------------------------------------------*/

	 @GetMapping("/getEnginByProc")
	 public Result<?> getEnginByProc(@RequestParam("procId") String procId,@RequestParam("engineName") String engineName,@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
									 @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize){
	 	Page<Engineering> page = new Page<>(pageNo, pageSize);
	 	return Result.ok(engineeringService.getEnginByProc(page,procId,engineName));
	 }

}
